package com.strong.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.security.KeyPair;

@Slf4j
public class KeyUtils {

    /**
     * 私钥文件
     */
    static String STR_PRIVATE_KEY_FILE = StrUtil.join(File.separator, FileUtil.getWebRoot(), "gitignore", "private.key");

    /**
     * 公钥文件
     */
    static String STR_PUBLIC_KEY_FILE = StrUtil.join(File.separator, FileUtil.getWebRoot(), "src", "main", "resources", "public.key");

    /**
     * UUID文件
     */
    static String STR_UUID_FILE = StrUtil.join(File.separator, FileUtil.getWebRoot(), "gitignore", "uuid");

    /**
     * 私钥字节数组
     */
    public final static byte[] BYTES_PRIVATE_KEY = FileUtil.exist(STR_PRIVATE_KEY_FILE) ? FileUtil.readBytes(STR_PRIVATE_KEY_FILE) : null;

    /**
     * 公钥字节数组
     */
    public final static byte[] BYTES_PUBLIC_KEY = FileUtil.exist(STR_PUBLIC_KEY_FILE) ? FileUtil.readBytes(STR_PUBLIC_KEY_FILE) : null;

    /**
     * UUID字符串
     */
    public final static String STR_UUID = FileUtil.exist(STR_UUID_FILE) ? FileUtil.readUtf8String(STR_UUID_FILE) : null;

    /**
     * 生成密钥对
     */
    private static void generateKeyPair() {
        // 获取密钥对象
        KeyPair pair = SecureUtil.generateKeyPair("SM2");
        // 删除现有密钥文件
        FileUtil.del(STR_PRIVATE_KEY_FILE);
        FileUtil.del(STR_PUBLIC_KEY_FILE);
        FileUtil.del(STR_UUID_FILE);
        // 写入密钥文件
        FileUtil.writeBytes(pair.getPrivate().getEncoded(), STR_PRIVATE_KEY_FILE);
        FileUtil.writeBytes(pair.getPublic().getEncoded(), STR_PUBLIC_KEY_FILE);
        FileUtil.writeUtf8String(IdUtil.simpleUUID(), STR_UUID_FILE);

        log.info("密钥对生成完毕：\n公钥：{}\n私钥：{}\n项目UUID：{}", STR_PRIVATE_KEY_FILE, STR_PUBLIC_KEY_FILE, STR_UUID_FILE);
    }

    /**
     * 生成测试加密、签名字符串
     */
    private static void generatePasswordEncode(String strPassword) {
        // 读取UUID
        String uuid = FileUtil.readUtf8String(STR_UUID_FILE);
        // 根据key文件获取sm2对象
        SM2 sm2 = SmUtil.sm2(FileUtil.readBytes(STR_PRIVATE_KEY_FILE), FileUtil.readBytes(STR_PUBLIC_KEY_FILE));

        // 生成签名字符串
        String strPasswordSign = HexUtil.encodeHexStr(sm2.sign(StrUtil.utf8Bytes(strPassword), StrUtil.utf8Bytes(uuid)));
        log.info("\n{} \n  签名结果 -> {}", strPassword, strPasswordSign);
        // 生成加密的字符串
        String strEncrypt = sm2.encryptBase64(strPassword, KeyType.PublicKey);
        log.info("\n{} \n  加密结果 -> {}", strPassword, strEncrypt);
        // 生成解密后的字符串
        String strDecrypt = sm2.decryptStr(strEncrypt, KeyType.PrivateKey);
        log.info("\n{} \n  解密结果 -> {}", strEncrypt, strDecrypt);
    }

    public static void main(String[] args) {
        generateKeyPair();
        generatePasswordEncode("springboot");

        SM2 sm2 = SmUtil.sm2(FileUtil.readBytes(STR_PRIVATE_KEY_FILE), FileUtil.readBytes(STR_PUBLIC_KEY_FILE));
        log.info("数据库账号：{}", sm2.encryptBase64("sa", KeyType.PublicKey));
        log.info("数据库密码：{}", sm2.encryptBase64("123456", KeyType.PublicKey));
    }
}
